package com.learn.im.servcie.impl;

import com.alibaba.fastjson.JSON;
import com.learn.im.domain.Chat;
import com.learn.im.domain.FileMessage;
import com.learn.im.enums.ChatType;
import com.learn.im.enums.MsgType;
import com.learn.im.servcie.IChatFileTranf;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.stereotype.Service;

import javax.websocket.Session;
import java.io.*;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Emp
 * @version :    1.0
 */
@Service("chatFileTranf")
@Slf4j
public class ChatFileTranfImpl implements IChatFileTranf {

    // 文件保存路径
    private static String FILE_PATH;
    @Value("${im.storage.path}")
    public void setFilePath(String path) {
        FILE_PATH = path;
    }
    private static ServerProperties serverProperties;
    @Autowired
    public void setServerPort(ServerProperties server){
        serverProperties = server;
    }


    /**
     * 接收文件
     */
    @Override
    public boolean saveFile(FileMessage file, byte[] message) {
        File f = file.getFile();
        // 如果目录不存在就创建
        if (!f.getParentFile().exists()) {
            boolean mkdirs = f.getParentFile().mkdirs();
        }
        try (OutputStream os = new FileOutputStream(f, true)) {
            os.write(message, 0, message.length);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 发送文件
     * type 0 发送文件二进制 1发送文件下载路径
     */
    @Override
    public boolean sendFile(int type, Session toSession, FileMessage finalFile) {
        if (toSession == null){
            log.error("文件发送失败,对方用户不在线");
            return false;
        }
        boolean res = false;
        switch (type){
            case 0:
                res = handleBinary(toSession,finalFile);
                // 二进制数据发送成功后删除临时文件
                if (res){
                    boolean delete = finalFile.getFile().delete();
                }
                break;
            case 1:
                res = handleDownloadLink(toSession,finalFile);
                break;
        }
        return res;
    }

    /**
     * 处理下载链接
     */
    @Override
    public boolean handleDownloadLink(Session toSession, FileMessage finalFile) {
        try {
            // 获取下载链接
            String filePath = finalFile.getFilePath();
            // 此处需要替换
            filePath = filePath.replace(File.separator,"/");
            // 当前项目url
            String url = "http://localhost:" + serverProperties.getPort() + "/download/file?filePath=" + filePath;
            Map<String, Object> content = new HashMap<>();
            content.put("file",finalFile.getOriginName());
            content.put("url",url);
            Chat message = Chat.builder()
                    .chatType(ChatType.NORMAL.name())
                    .msgType(MsgType.FILE.name())
                    .from(finalFile.getChat().getFrom())
                    .to(finalFile.getChat().getTo())
                    .time(new Date())
                    .content(JSON.toJSONString(content))
                    .build();
            toSession.getBasicRemote().sendText(JSON.toJSONString(message));
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 处理二级制流
     */
    @Override
    public boolean handleBinary(Session toSession, FileMessage finalFile) {
        File file = new File(FILE_PATH + finalFile.getFilePath());
        finalFile.setFile(file);
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))){
            Map<String, Object> content = new HashMap<>();
            content.put("sumSize",file.length());
            content.put("orgName",finalFile.getOriginName());
            // 先发送FILE类型消息表示开始发送文件
            Chat message = Chat.builder()
                    .from(finalFile.getChat().getFrom())
                    .to(finalFile.getChat().getTo())
                    .time(new Date())
                    .content(JSON.toJSONString(content))
                    .msgType(MsgType.FILE.name())
                    .build();
            toSession.getBasicRemote().sendText(JSON.toJSONString(message));

            // 发送文件分片
            byte[] chunk = new byte[finalFile.getChunk()];
            long count = (file.length() % chunk.length) == 0 ? (file.length() / chunk.length) : (file.length() / chunk.length) + 1;
            for (int i = 0; i < count; i++) {
                int len = bis.read(chunk);
                if (i == count-1){
                    // 写出最后一块分片
                    toSession.getBasicRemote().sendBinary(ByteBuffer.wrap(chunk,0,len),true);
                }else {
                    toSession.getBasicRemote().sendBinary(ByteBuffer.wrap(chunk,0,len));
                }
            }

            // 发送FILE_END 表示文件发送完毕
            message.setMsgType(MsgType.FILE.name());
            toSession.getBasicRemote().sendText(JSON.toJSONString(message));
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean handleImg(Session toSession, FileMessage finalFile) {
        try {
            // 获取图片链接
            String filePath = finalFile.getFilePath();
            // 此处需要替换
            filePath = filePath.replace(File.separator,"/");
            // 当前项目url
            String url = "http://localhost:" + serverProperties.getPort() + "/download/img?filePath=" + filePath;
            Map<String, Object> content = new HashMap<>();
            content.put("img",finalFile.getOriginName());
            content.put("url",url);
            Chat message = Chat.builder()
                    .chatType(ChatType.NORMAL.name())
                    .msgType(MsgType.PIC.name())
                    .from(finalFile.getChat().getFrom())
                    .to(finalFile.getChat().getTo())
                    .time(new Date())
                    .content(JSON.toJSONString(content))
                    .build();
            toSession.getBasicRemote().sendText(JSON.toJSONString(message));
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

}
